﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.IO;

namespace PlotDesigner
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        public PlotNode beginNode = new PlotNode();
        private void MainForm_Load(object sender, EventArgs e)
        {
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            beginNode.father = null;
            refreshPlot();
            changeTitle();
        }
        //刷新节点显示
        public void refreshPlot()
        {
            panel.Controls.Clear();
            showPlot(beginNode);
            drawPlot(beginNode);
            Graphics g;
            g = Program.mainform.panel.CreateGraphics();
            g.Clear(Color.White);
            DrawLine(beginNode, g);
        }
        //绘制各个节点
        public void showPlot(PlotNode pn)
        {
            if ((bool)(pn.father?.isFold == true)) return;
            panel.Controls.Add(pn);
            if (pn.next != null)
                showPlot(pn.next);
            foreach(PlotNode branch in pn.branches)
            {
                showPlot(branch);
            }
            return;
        }
        //绘制各个节点
        void drawPlot(PlotNode begin)
        {
            begin.Place(begin.Left, begin.Top);
        }
        //获取某个节点连接到的下一个节点
        private PlotNode getFa(PlotNode pn)
        {
            if (pn == null) return pn;
            if (pn.father == null) return pn;
            if(pn.father.next == null)
            {
                return getFa(pn.father);
            }
            return pn.father;
        }
        //绘制各个节点的之间的连线
        public void DrawLine(PlotNode pn ,Graphics g)
        {
            if (pn == null) return;
            if ((bool)(pn.father?.isFold == true)) return;
            if (pn.isEnded) return;

            Pen p = new Pen(Color.Black, 1);
            
            foreach (PlotNode branch in pn.branches)
            {
                if ((bool)(branch.father?.isFold == true)) continue;
                p.Color = Color.Blue;
                g.DrawLine(p, pn.Left + pn.Width / 2, pn.Top, pn.Left + pn.Width / 2, branch.Top + branch.Height / 2);
                g.DrawLine(p, pn.Left + pn.Width / 2, branch.Top + branch.Height / 2, branch.Left, branch.Top + branch.Height / 2);
                g.DrawString(branch.condition, new Font("新宋体", 10), new SolidBrush(Color.Black), pn.Left + pn.Width / 2, branch.Top + branch.Height / 2 - 12);
                DrawLine(branch, g);
            }

            if (pn.next == null)
            {
                PlotNode fa = pn.father;
                if(fa == null)
                {
                    //pn是根节点,啥都不用干
                }
                else
                {
                    fa = getFa(pn);
                    if(fa!=null && fa.next != null)
                    {
                        p.Color = Color.Red;
                        g.DrawLine(p, pn.Right, pn.Top + pn.Height / 2, fa.next.Left + fa.next.Width / 3, pn.Top + pn.Height / 2);
                        g.DrawLine(p, fa.next.Left + fa.next.Width / 3, pn.Top + pn.Height / 2, fa.next.Left + fa.next.Width / 3, fa.next.Top);
                    }
                }
                
            }

            //绘制当前节点到next的线段
            Pen p2 = new Pen(Color.Black, 1) { DashStyle = System.Drawing.Drawing2D.DashStyle.Custom };
            if ((bool)(pn.isFold != true))
            {
                p2.Color = Color.Black;
                p2.Width = 1;
            }
            else
            {
                p2.Color = Color.Red;
                p2.Width = 3;
            }
            
            p2.DashPattern = new float[] { 1f, 1f };
            if (pn.next != null)
            {
                g.DrawLine(p2, pn.Right, pn.Top + pn.Height / 2, pn.next.Left, pn.next.Top + pn.next.Height / 2);
            }

            DrawLine(pn.next, g);
        }
        //调整窗口大小以后重新排列剧情节点
        private void MainForm_Resize(object sender, EventArgs e)
        {
            refreshPlot();
        }

        private void OnPaint(object sender, PaintEventArgs e)
        {

        }

        private void OnScroll(object sender, ScrollEventArgs e)
        {
            refreshPlot();
        }

        private void menuStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        private bool moveFlag;
        private int mouseBeginX, mouseBeginY;
        private int nodeBeginX, nodeBeginY;
        private void OnMouseDown(object sender, MouseEventArgs e)
        {
            moveFlag = true;
            mouseBeginX = e.X;
            mouseBeginY = e.Y;
            nodeBeginX = beginNode.Left;
            nodeBeginY = beginNode.Top;
        }

        private XmlElement sourceToXml(XmlDocument doc)
        {
            XmlElement xe_source = doc.CreateElement("sources");
            XmlElement xe_speakers_list = doc.CreateElement("speakers_list");

            foreach (string s in Source.speakerList)
            {
                XmlElement xe_speaker = doc.CreateElement("speaker");
                xe_speaker.SetAttribute("name", s);
                xe_speakers_list.AppendChild(xe_speaker);
            }
            xe_source.AppendChild(xe_speakers_list);
            return xe_source;
        }

        private void SaveFileClick(object sender, EventArgs e)
        {
            XmlDocument doc = new XmlDocument();
            XmlElement xmlPlot = beginNode.toXml(doc);
            XmlElement xmlSource = sourceToXml(doc);
            XmlElement xml = doc.CreateElement("plot");
            xml.AppendChild(xmlPlot);
            xml.AppendChild(xmlSource);
            if(Source.path == null)
            {
                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string filename;
                    filename = saveFileDialog.FileName;
                    Source.path = filename;

                    File.WriteAllText(filename, xml.OuterXml);
                }
            }
            else
            {
                File.WriteAllText(Source.path, xml.OuterXml);
            }
            changeTitle();
        }

        void AppendDialogNode(DialogNode beginDlg, DialogNode nextDlg)
        {
            DialogNode dn = beginDlg;
            while(dn.next != null)
            {
                dn.next.last = dn;
                dn = dn.next;
            }
            dn.next = nextDlg;

        }

        void AppendPlotNode(PlotNode beginNode, PlotNode nextNode)
        {
            PlotNode cur = beginNode;
            while(cur.next != null)
            {
                cur.next.last = cur;
                cur = cur.next;
            }
            cur.next = nextNode;
        }

        DialogNode xmlToDialogNode(XmlNode node, PlotNode p)
        {
            //Console.WriteLine(node.OuterXml);
            DialogNode dn = new DialogNode(p);
            dn.Speaker = ((XmlElement)node).GetAttribute("speaker");
            XmlNode xn_val = node.SelectSingleNode("value");
            dn.DlgValue = xn_val.InnerText;
            XmlNode xn_rtf = node.SelectSingleNode("rtf");
            if(xn_rtf != null)
                dn.DlgRtf = xn_rtf.InnerText;
            return dn;
        }

        List<DialogNode> xmlToDialogNodeList(XmlNodeList nodelist, PlotNode pn)
        {
            List<DialogNode> node_list = new List<DialogNode>();
            foreach(XmlNode node in nodelist)
            {
                node_list.Add(xmlToDialogNode(node, pn));
            }
            return node_list;
        }

        PlotNode xmlToPlotNode(XmlNode node)
        {
            XmlNodeList xml_dlgs = node.SelectNodes("Dialogs/dialog");
            PlotNode pn = new PlotNode();

            List<DialogNode> dlgs = xmlToDialogNodeList(xml_dlgs, pn);
            pn.plotName = ((XmlElement)node).GetAttribute("plotName");
            pn.condition = ((XmlElement)node).GetAttribute("condition");
            pn.isEnded = ((XmlElement)node).GetAttribute("isEnded") == "True";
            pn.isFold = ((XmlElement)node).GetAttribute("isFold") == "True";
            pn.isVolume = ((XmlElement)node).GetAttribute("isVolume") == "True";
            pn.isChapter = ((XmlElement)node).GetAttribute("isChapter") == "True";
            pn.beginDlg = new DialogNode(pn);
            pn.beginDlg = dlgs[0];
            
                if (dlgs.Count > 1)
                {
                    for (int dlg_count = 1; dlg_count < dlgs.Count; dlg_count++)
                    {
                        DialogNode dlg = dlgs[dlg_count];
                        AppendDialogNode(pn.beginDlg, dlg);
                    }
                }
            XmlNodeList xml_branches = node.SelectNodes("branchList/plotNodeList/plotNode");
            List<PlotNode> plots = xmlToPlotNodeList(xml_branches);
            foreach (PlotNode plot in plots) plot.father = pn;
            pn.branches = plots;
            pn.refreshDlg();
            //Console.WriteLine(pn.beginDlg.Speaker);
            return pn;
        }

        List<PlotNode> xmlToPlotNodeList(XmlNodeList nodelist)
        {
            List<PlotNode> plotNode_list = new List<PlotNode>();
            foreach(XmlNode node in nodelist)
            {
                PlotNode n = xmlToPlotNode(node);
                //Console.WriteLine(n.beginDlg.Speaker);
                plotNode_list.Add(n);
            }
            return plotNode_list;
            
        }

        private void xmlToSource(XmlNode node)
        {
            XmlNodeList speakers = node.SelectNodes("speakers_list/speaker");
            Source.speakerList.Clear();
            foreach(XmlNode speaker in speakers)
            {
                string s = ((XmlElement)speaker).GetAttribute("name");
                Source.speakerList.Add(s);
            }
        }

        void changeTitle()
        {
            if(Source.path != "")
            {
                Text = "剧情设计器 - " + Source.path;
            }
            else
            {
                Text = "剧情设计器 - 未命名";
            }
        }

        private void OpenFileClick(object sender, EventArgs e)
        {
            if(openFileDialog.ShowDialog() == DialogResult.OK)
            {
                string filename = openFileDialog.FileName;
                Source.path = filename;
                changeTitle();
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(File.ReadAllText(filename));
                XmlNodeList rootlist = doc.SelectNodes("plot/plotNodeList/plotNode");
                List<PlotNode> plotnode_list = xmlToPlotNodeList(rootlist);

                if (plotnode_list.Count >= 1)
                {
                    beginNode = plotnode_list[0];
                    //Console.WriteLine(beginNode.beginDlg.Speaker);
                    beginNode.last = null;
                    if(plotnode_list.Count > 1)
                    {
                        for (int plot_count = 1; plot_count < plotnode_list.Count; plot_count++)
                        {
                            PlotNode pn = plotnode_list[plot_count];
                            pn.refreshDlg();
                            AppendPlotNode(beginNode, pn);
                        }
                    }
                }
                else
                {
                    beginNode = new PlotNode();
                }

                XmlNode source = doc.SelectSingleNode("plot/sources");
                xmlToSource(source);
            }
            refreshPlot();
        }

        private void SpeakerListEditorClick(object sender, EventArgs e)
        {
            SpeakerListEditor sle = new SpeakerListEditor();
            sle.Show();
        }

        private void SaveAsClick(object sender, EventArgs e)
        {
            XmlDocument doc = new XmlDocument();
            XmlElement xmlPlot = beginNode.toXml(doc);
            XmlElement xmlSource = sourceToXml(doc);
            XmlElement xml = doc.CreateElement("plot");
            xml.AppendChild(xmlPlot);
            xml.AppendChild(xmlSource);
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                string filename;
                filename = saveFileDialog.FileName;
                Source.path = filename;

                File.WriteAllText(filename, xml.OuterXml);
            }
            changeTitle();
        }

        private void NewFileClick(object sender, EventArgs e)
        {
            if(MessageBox.Show("我也不知道你保存了没,\n确定要新建吗？","新建",MessageBoxButtons.OKCancel) == DialogResult.OK)
            {
                beginNode = new PlotNode();
                refreshPlot();
            }
        }

        private void 关闭ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("我也不知道你保存了没,\n确定要关闭吗？", "关闭", MessageBoxButtons.OKCancel) == DialogResult.OK)
            {
                Application.Exit();
            }
        }

        private void OnMouseUp(object sender, MouseEventArgs e)
        {
            //beginNode.Left += e.X - mouseBeginX;
            //beginNode.Top += e.Y - mouseBeginY;
            moveFlag = false;
            refreshPlot();
        }

        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            if (!moveFlag) return;
            int dx = e.X - mouseBeginX;
            int dy = e.Y - mouseBeginY;
            beginNode.Left = nodeBeginX + dx;
            beginNode.Top = nodeBeginY + dy;
        }

    }
}
